# gozerbot/xmpp/message.py
#
#

""" jabber message definition .. types can be normal, chat, groupchat, 
    headline or  error
"""

__copyright__ = 'this file is in the public domain'

# gozerbot imports
from gozerbot.utils.exception import handle_exception
from gozerbot.utils.log import rlog
from gozerbot.utils.trace import whichmodule
from gozerbot.utils.generic import toenc, fromenc, jabberstrip, makeargrest
from gozerbot.utils.locking import lockdec
from gozerbot.eventbase import EventBase
from gozerbot.config import config

# xmpp imports
from core import XMLDict

# basic imports
import types, time, thread

# locks
replylock = thread.allocate_lock()
replylocked = lockdec(replylock)

if config['dotchars']:
    dotchars = config['dotchars']
else:
    dotchars = ' .. '

class Message(EventBase):

    """ jabber message object. """

    def __init__(self, nodedict={}, bot=None):
        EventBase.__init__(self, nodedict, bot)
        self.element = "message"
        self.jabber = True
        rlog(2, whichmodule(1), 'MESSAGE: ' + str(self))

    def __copy__(self):
        return Message(self, self.bot)

    def __deepcopy__(self, bla):
        return Message(self, self.bot)

                 
    #@replylocked
    def reply(self, txt, result=None, nick=None, dot=False, nritems=False, nr=False, fromm=None, private=False):

        """ reply txt. """

        if result == []:
            return

        restxt = ""

        if type(result) == types.DictType:

            for i, j in result.iteritems():
                if type(j) == types.ListType:
                    try:
                        z = dotchars.join(j)
                    except TypeError:
                        z = unicode(j)
                else:
                    z = j
                if dot == True:
                    restxt += "%s: %s %s " % (i, z, dotchars)
                elif dot:
                    restxt += "%s: %s %s " % (i, z, dot)
                else:
                    restxt += "%s: %s " % (i, z)

            if restxt:
                if dot == True:
                    restxt = restxt[:-6]
                elif dot:
                    restxt = restxt[:-len(dot)]
        lt = False

        if type(txt) == types.ListType and not result:
            result = txt
            origtxt = ""
            lt = True
        else:
            origtxt = txt

        if result:
            lt = True

        if self.queues:
            for i in self.queues:
                if lt:
                    for j in result:
                        i.put_nowait(j)
                else:
                    i.put_nowait(txt)
            if self.onlyqueues:
                return

        pretxt = origtxt

        if lt and not restxt:
            res = []
            for i in result:
                if type(i) == types.ListType or type(i) == types.TupleType:
                    try:
                        res.append(dotchars.join(i))
                    except TypeError:
                        res.append(unicode(i))
                else:
                    res.append(i)
            result = res
            if nritems:
                if len(txt) > 1:
                    pretxt = "(%s items) .. " % len(result)
            txtlist = [unicode(i) for i in result]
            if not nr is False:
                try:
                    start = int(nr)
                except ValueError:
                    start = 0
                txtlist2 = []
                teller = start
                for i in txtlist:
                    txtlist2.append("%s) %s" % (teller, i))
                    teller += 1
                txtlist = txtlist2
            if dot == True:
                restxt = dotchars.join(txtlist)
            elif dot:
                restxt = dot.join(txtlist)
            else:
                restxt = ' '.join(txtlist)

        if pretxt:
            restxt = pretxt + restxt

        txt = jabberstrip(restxt)

        if not txt:
            return

        what = txt
        txtlist = []
        start = 0
        end = 900
        length = len(what)

        for i in range(length/end+1):
            endword = what.find(' ', end)
            if endword == -1:
                endword = end
            txtlist.append(what[start:endword])
            start = endword
            end = start + 900

        size = 0

        # see if we need to store output in less cache
        if len(txtlist) > 1:
            self.bot.less.add(self.userhost, txtlist)
            size = len(txtlist) - 1
            result = txtlist[:1][0]
            if size:
                result += " (+%s)" % size
        else:
            result = txtlist[0]

        if self.filtered(result):
            return

        try:
            to = self.options['--to']
        except KeyError:
            to = None

        outtype = self.type

        if to and to in self.bot.state['joinedchannels']:
            outtype = 'groupchat' 
            self.groupchat = True
            self.msg = False

        repl = Message({'from': self.me, 'to': to or self.jid, 'type': outtype, 'txt': result})

        if self.groupchat:
            if self.resource == self.bot.nick:
                return
            if to:
                pass
            elif nick:
                repl.type = 'chat'
            elif private:
                repl.to = self.userhost
            elif self.printto:
                repl.to = self.printto
            else:
                repl.to = self.channel

        #repl['from'] = self.bot.me

        if nick:
            repl.type = 'normal'
        elif not repl.type:
            repl.type = 'chat'

        self['bot'].send(repl)

    def toirc(self):

        """ set ircevent compat attributes. """

        self.jidchange = False
        self.cmnd = 'Message'

        try:
            self.resource = self.fromm.split('/')[1]
        except IndexError:
            pass

        self.channel = self['fromm'].split('/')[0]
        self.origchannel = self.channel
        self.nick = self.resource

        try:
            if self.bot:
                self.jid = self.bot.jids[self.channel][self.resource]
                self.jidchange = True
            else:
                self.jid = self.fromm
        except KeyError:
            self.jid = self.fromm

        self.ruserhost = self.jid
        self.userhost = self.jid
        self.stripped = self.jid.split('/')[0]
        self.printto = self.channel

        for node in self.subelements:
            try:
                self.txt = node.body.data
            except (AttributeError, ValueError):
                continue
        self.origtxt = self.txt
        self.time = time.time()

        if self.type == 'groupchat':
            self.groupchat = True
            if self.jidchange:
                self.userhost = self.stripped
        else:
            self.groupchat = False
            self.userhost = self.stripped

        self.msg = not self.groupchat

    def errorHandler(self):
        try:
            code = self.get('error').code
        except Exception, ex:
            handle_exception()
        try:
            method = getattr(self, "handle_%s" % code)
            if method:
                rlog(10, 'message', 'dispatching error to handler %s' % str(method))
                method(self)
        except AttributeError, ex:
            rlog(10, 'message', 'unhandled error %s' % code)
        except:
            handle_exception()

